﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WasaWasa
{
    /// <summary>
    /// 文字列の暗号化処理を行います。
    /// </summary>
    class DESStringCrypto
    {
        private const string _ = "http://titanurl.com/940d7d5454d42becc6ad2ededd045cc0024dd425cbeda0d6e4ed5ccd5e5e0d90e54062d66ebda2b002657d00a4de4d6724e44d4c4e79a0e4e6eb4444d2924c0ac49540eee0425475eea4aaced64dce5eb0464b4ceee52d4444bae60eb2040270ec00b5cadc6e0e45ddcb72ac00d4/d2e6ee469ad064d06c770900dd9cd2ed0e40e97b445c20c5c9e06cc646eae6cbd4400594ede24de904ed2a7d62042d442a2c9444edde425c4040e400c6050044ec0ed2004c4eea6cde0ab4b67cd400d720ed90c4dd04d64b5de0cb5ddd7eebc650547e670952dc7b6cad2c6c624c/c4e60c6646a4d40474d4c5c424e464a2aced00ece0a66922d67e455cc255a5a66d66c90492ea646c6da67abe0cb0ec40cc096e62decd505ce60c5e6a6e4d5aec6454aed65d744c0a0e06ccdec242d2e756aa62754d04a4c72ac4c0647444ed4a4a0dc6b55d4dcc4074ee0eeed0dc/20eec0dd47464ee4cbd240e74b60ec6dda4a60a5502ad2ce4e64d0d4c5464d0d644cd6444250ec6642c7e0e4a400d072a2969d456ade044254e00d4aaab06dd04247eade5494007000002224edaaed2c66654245dc4e04e9506c7e650020cccdc4dcb4e0a7e6e667c06a5540544d/a5440e60e0097ed009246d4466ee95ea0b64292029dd44500da4acbed5ecd75e9d7ecec404e4c6e2ec54665dacd490ccaae47de40eb4cbc4a27c20064d4064e444ad440225e24b674446dc420e02e24c4dd574ddd05900d5402ae42042e0b60ed2eeb66790bc247ea4de460ceedd/adad49ae54654206c54eace44dce4bcb2ceca0ecc44eedc0ac605e624e2047da540dd5a4d4e40ce6d2d4cdd44ca50e60ae62dd440c7e260244ee44764e4406c4420450c70ee6ae0ecd0dd2e694ea6ed004d6d02cd0c05e5d6950b76ac646da40a407b4bd0e0020e64c745d4ee04a/4cb0ecdeaddc2d0ad5dd054d44e6c940a5246ca626c26e64a4950ebc444942442200ba6dd6e404cc40d42d9c2ac020566d50ed4da5504a06dddc7d44d42e64dd76ddadccc45e4d0240406e5db7ab244dbe4260e5e5e5794de9cc4eac5c449ace64c504d44eb402de6d5cc044e0e2/eed066b6e6c950456d46b42e404ebae4d00cddaa5d4eda5ae02d2da04ac46cc2a74ce66006454ee44ceed646065b000cccc9d2e45c4d92e4ed6ce4dd05bc56cc50ca44ad9ec46acc67dc242ea464060474e54cd6c9bdc56ec4d0b42e600949c4025660256cb6420da444d92bda64/ec4ad0dc9242900dede0beb4e470c90b9d5d474a064544ddcd66e2eedc2bd52d05dc5cb0204aae0b9a9450d4be6d06ad6064d9745e0224620eccd06e07e6c4d704adbca2da42e457c26cceeb25eed44445465cacab6e4cdb074ee409066d9d4c06ee4e0554bde095526d4e266dce";

        /// <summary>
        /// 文字列を暗号化する
        /// </summary>
        /// <param name="str">暗号化する文字列</param>
        /// <param name="key">パスワード</param>
        /// <returns>暗号化された文字列</returns>
        public static string EncryptString(string str)
        {
            string key = _;

            //文字列をバイト型配列にする
            byte[] bytesIn = System.Text.Encoding.UTF8.GetBytes(str);

            //DESCryptoServiceProviderオブジェクトの作成
            System.Security.Cryptography.DESCryptoServiceProvider des =
                new System.Security.Cryptography.DESCryptoServiceProvider();

            //共有キーと初期化ベクタを決定
            //パスワードをバイト配列にする
            byte[] bytesKey = System.Text.Encoding.UTF8.GetBytes(key);
            //共有キーと初期化ベクタを設定
            des.Key = ResizeBytesArray(bytesKey, des.Key.Length);
            des.IV = ResizeBytesArray(bytesKey, des.IV.Length);

            //暗号化されたデータを書き出すためのMemoryStream
            System.IO.MemoryStream msOut = new System.IO.MemoryStream();
            //DES暗号化オブジェクトの作成
            System.Security.Cryptography.ICryptoTransform desdecrypt =
                des.CreateEncryptor();
            //書き込むためのCryptoStreamの作成
            System.Security.Cryptography.CryptoStream cryptStreem =
                new System.Security.Cryptography.CryptoStream(msOut,
                desdecrypt,
                System.Security.Cryptography.CryptoStreamMode.Write);
            //書き込む
            cryptStreem.Write(bytesIn, 0, bytesIn.Length);
            cryptStreem.FlushFinalBlock();
            //暗号化されたデータを取得
            byte[] bytesOut = msOut.ToArray();

            //閉じる
            cryptStreem.Close();
            msOut.Close();

            //Base64で文字列に変更して結果を返す
            return System.Convert.ToBase64String(bytesOut);
        }

        /// <summary>
        /// 暗号化された文字列を復号化する
        /// </summary>
        /// <param name="str">暗号化された文字列</param>
        /// <param name="key">パスワード</param>
        /// <returns>復号化された文字列</returns>
        public static string DecryptString(string str)
        {
            string key = _;

            if (String.IsNullOrEmpty(str))
            {
                return "";
            }

            //DESCryptoServiceProviderオブジェクトの作成
            System.Security.Cryptography.DESCryptoServiceProvider des =
                new System.Security.Cryptography.DESCryptoServiceProvider();

            //共有キーと初期化ベクタを決定
            //パスワードをバイト配列にする
            byte[] bytesKey = System.Text.Encoding.UTF8.GetBytes(key);
            //共有キーと初期化ベクタを設定
            des.Key = ResizeBytesArray(bytesKey, des.Key.Length);
            des.IV = ResizeBytesArray(bytesKey, des.IV.Length);

            //Base64で文字列をバイト配列に戻す
            byte[] bytesIn = System.Convert.FromBase64String(str);
            //暗号化されたデータを読み込むためのMemoryStream
            System.IO.MemoryStream msIn =
                new System.IO.MemoryStream(bytesIn);
            //DES復号化オブジェクトの作成
            System.Security.Cryptography.ICryptoTransform desdecrypt =
                des.CreateDecryptor();
            //読み込むためのCryptoStreamの作成
            System.Security.Cryptography.CryptoStream cryptStreem =
                new System.Security.Cryptography.CryptoStream(msIn,
                desdecrypt,
                System.Security.Cryptography.CryptoStreamMode.Read);

            //復号化されたデータを取得するためのStreamReader
            System.IO.StreamReader srOut =
                new System.IO.StreamReader(cryptStreem,
                System.Text.Encoding.UTF8);
            //復号化されたデータを取得する
            string result;
            result = srOut.ReadToEnd();

            //閉じる
            srOut.Close();
            cryptStreem.Close();
            msIn.Close();

            return result;
        }

        /// <summary>
        /// 共有キー用に、バイト配列のサイズを変更する
        /// </summary>
        /// <param name="bytes">サイズを変更するバイト配列</param>
        /// <param name="newSize">バイト配列の新しい大きさ</param>
        /// <returns>サイズが変更されたバイト配列</returns>
        private static byte[] ResizeBytesArray(byte[] bytes, int newSize)
        {
            byte[] newBytes = new byte[newSize];
            if (bytes.Length <= newSize)
            {
                for (int i = 0; i < bytes.Length; i++)
                    newBytes[i] = bytes[i];
            }
            else
            {
                int pos = 0;
                for (int i = 0; i < bytes.Length; i++)
                {
                    newBytes[pos++] ^= bytes[i];
                    if (pos >= newBytes.Length)
                        pos = 0;
                }
            }
            return newBytes;
        }

    }
}
